package org.jiucheng.magpiebridge.transfer.aio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.CompletionHandler;
import java.nio.channels.SocketChannel;

import org.jiucheng.magpiebridge.protocol.Message;
import org.jiucheng.magpiebridge.util.ThreadManager;

/**
 * 
 * @author jiucheng
 *
 */
public class TransferConnectedCompletionHandler implements CompletionHandler<Integer, TransferAttachment> {
	
	public void completed(Integer result, final TransferAttachment attachment) {
		if (attachment.getWriteByteBuffer().hasRemaining()) {
			attachment.getClient().write(attachment.getWriteByteBuffer(), attachment, this);
			return;
		}
		attachment.writed.compareAndSet(true, false);
		
		attachment.setWriteByteBuffer(null);
		ByteBuffer readByteBuffer = ByteBuffer.allocate(13);
		attachment.getClient().read(readByteBuffer, attachment.setReadByteBuffer(readByteBuffer), new TransferReadCompletionHandler());
		
        ThreadManager.singleton().execute(new Runnable() {
            public void run() {
            	// 16KB
                ByteBuffer buf = ByteBuffer.allocate(16 * 1024);
                while(true) {
                	if (attachment.canReaded()) {
	                    SocketChannel real = attachment.getRealSocketChannel();
	                    if (real == null)  {
	                    	buf = null;
	                        return;
	                    }
	                    int len;
	                    try {
	                        len = real.read(buf);
	                    } catch (IOException e) {
	                        buf = null;
	                        attachment.disconnect();
	                        return;
	                    }
	                    if (len == -1) {
	                        buf = null;
	                        attachment.disconnect();
	                        return;
	                    } else if (len > 0) {
	                        buf.flip();
	                        Message message = new Message();
	                        message.setMagic(Message.MAGIC);
	                        message.setType(Message.Type.TRANSFER);
	                        message.setUri(attachment.getUri());
	                        byte[] bts = new byte[len];
	                        buf.get(bts);
	                        message.setData(bts);
	                        message.setSize(bts.length);
	                        ByteBuffer buffer = Message.toByteBuffer(message);
	                        if (attachment.canWrited()) {
	                            attachment.getClient().write(buffer, attachment.setWriteByteBuffer(buffer), new TransferWriteCompletionHandler());
	                            buf.clear();
	                        }
	                    }
                	}
                }
            }
        });
	}
	
	public void failed(Throwable exc, TransferAttachment attachment) {
		attachment.writed.compareAndSet(true, false);
		attachment.close();
	}
}
